# -*- coding: utf-8 -*-
import logging, random, json
# import asyncio, aiohttp
import concurrent.futures, codecs
from urllib.parse import urlparse



import requests

from django.core.cache import cache
from django.conf import settings

from common.models import ViewModel, SiteTaxonomy
from common.ebook import EPubFactory

from novel import dao

class ExecutorMixin:
    def get_executor_class(self, m):
        executor_class = None
        if m == 'thread':
            executor_class = concurrent.futures.ThreadPoolExecutor
        elif m == 'process':
            executor_class = concurrent.futures.ProcessPoolExecutor
        else:
            raise ValueError()
        return executor_class

class SiteParseMixin:
    def get_host(self, url):
        o = urlparse(url)
        host = o.scheme + '://' + o.netloc
        return host
    
    def get_site_name(self, url):
        uri = urlparse(url)
        site_name = uri.netloc
        site_name = site_name[site_name.index('.') + 1:]
        site_name = site_name[0:site_name.index('.')]
        return site_name




class PersistenceMixin:
    def save_to_db(self, books, url=None):
        self.log.debug('SAVE %s to db', url)
        dao.save_books(((self.host or books.host), SiteTaxonomy.Book), books)

    def save_to_txt(self, book, url=None):
        self.log.debug('SAVE %s to txt', url)

    def save_to_epub(self, book, url=None):
        self.log.debug('SAVE %s to epub', url)
        factory = EPubFactory(book)
        factory.generate()

    def save_to_md(self, book, url=None):
        self.log.debug('SAVE %s to md', url)
        with codecs.open(book.title + '.md', 'w', 'utf-8') as f:
            f.write('----\n%s\n----\n' % (book.title,))
            f.write(book.author + '\n')
            for chapter in book.chapters:
                f.write('# %s\n' % (chapter.title,))
                if hasattr(chapter, 'content'):
                    f.write(chapter.content + '\n')    



# class AsyncHttpMixin(SiteParseMixin):
#     s = None
#     log = logging.getLogger('book.robot')
#     allow_redirects = False

#     def get_host(self, url):
#         o = urlparse(url)
#         host = o.scheme + '://'+ o.netloc        
#         return host

#     async def get_r(self, url, allow_redirects=None):
#         host = self.host or self.get_host(url)
#         headers = {
#             'Referer': host,
#             'User-Agent': random.choice(settings.USER_AGENT_LIST)}
              
#         if not self.s:
#             self.s = aiohttp.ClientSession(headers=headers)
#             #self.s.headers.update(headers)
#         if allow_redirects is None:
#             r = await self.s.get(url, allow_redirects = self.allow_redirects)
#         else:
#             r = await self.s.get(url, allow_redirects = allow_redirects)
#         return   r

#     async def get_html(self, url, allow_redirects=None):
#         self.log.debug('GET  ' + url)
#         html = cache.get(url)
#         if html:
#             self.log.debug('HIT  ' + url)
#         else:
#             r = await self.get_r(url, allow_redirects=allow_redirects)
#             html = await r.text()
#             self.log.debug('GET  %s %s', url, r.status)
#             #r.raise_for_status()
#             cache.set(url, html, 3600 * 5)
#         return html

#     async def get_content(self, url, allow_redirects=None):
#         self.log.debug('GET  ' + url)
#         html = cache.get(url)
#         if html:
#             self.log.debug('HIT  ' + url)
#         else:
#             r = await self.get_r(url, allow_redirects=allow_redirects)
#             html = await r.text()
#             self.log.debug('GET  %s %s', url, r.status)
#             #r.raise_for_status()
#             cache.set(url, html, 3600 * 5)
#         return html

#     async def get_json(self, url, allow_redirects=None):
#         self.log.debug('GET  ' + url)
#         result = cache.get(url)
#         if result:
#             self.log.debug('HIT  ' + url)
#         else:
#             r = await self.get_r(url, allow_redirects=allow_redirects)
#             try:
#                 result = await r.json()
#                 self.log.debug('GET  %s %s', url, r.status)
#                 #r.raise_for_status()
#                 cache.set(url, result, 3600 * 5)
#             except json.decoder.JSONDecodeError:
#                 self.log.exception('decode json failed %s %s', url, r.text)
#         return result

class HttpMixin(SiteParseMixin):
    s = None
    log = logging.getLogger('book.robot')
    allow_redirects = False

    def get_host(self, url):
        o = urlparse(url)
        host = o.scheme + '://'+ o.netloc        
        return host

    def get_r(self, url, allow_redirects=None):
        host = self.host or self.get_host(url)
        headers = {
            'Referer': host,
            'User-Agent': random.choice(settings.USER_AGENT_LIST)}
              
        if not self.s:
            self.s = requests.Session()
            self.s.headers.update(headers)
        if allow_redirects is None:
            r = self.s.get(url, allow_redirects = self.allow_redirects)
        else:
            r = self.s.get(url, allow_redirects = allow_redirects)
        return r

    def get_html(self, url, allow_redirects=None):
        self.log.debug('GET  ' + url)
        html = cache.get(url)
        if html:
            self.log.debug('HIT  ' + url)
        else:
            r = self.get_r(url, allow_redirects=allow_redirects)
            html = r.text
            self.log.debug('GET  %s %s', url, r.status_code)
            r.raise_for_status()
            cache.set(url, html, 3600 * 5)
        return html

    def get_content(self, url, allow_redirects=None):
        self.log.debug('GET  ' + url)
        html = cache.get(url)
        if html:
            self.log.debug('HIT  ' + url)
        else:
            r = self.get_r(url, allow_redirects=allow_redirects)
            html = r.content
            self.log.debug('GET  %s %s', url, r.status_code)
            r.raise_for_status()
            cache.set(url, html, 3600 * 5)
        return html

    def get_json(self, url, allow_redirects=None):
        self.log.debug('GET  ' + url)
        result = cache.get(url)
        if result:
            self.log.debug('HIT  ' + url)
        else:
            r = self.get_r(url, allow_redirects=allow_redirects)
            try:
                result = r.json()
                self.log.debug('GET  %s %s', url, r.status_code)
                r.raise_for_status()
                cache.set(url, result, 3600 * 5)
            except json.decoder.JSONDecodeError:
                self.log.exception('decode json failed %s %s', url, r.text)
        return result
